package com.shenma2009.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 12692
 * @version 1.0
 * @description: HttpClientUtil
 * @date 2023/5/13 9:27
 */

public class HttpClientUtil {

    private static final String DEFAULT_ENCODING = "UTF-8";

    /**
     * GET方式请求
     *
     * @param uri
     *            服务器的uri要用物理IP或域名,不识别localhost或127.0.0.1形式!
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String get(String uri) throws ClientProtocolException,
            IOException {
        HttpGet httpGet = new HttpGet(uri);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpResponse httpResponse = httpClient.execute(httpGet);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
//            String result = EntityUtils.toString(httpResponse.getEntity());
            return EntityUtils.toString(httpResponse.getEntity());
        }
        throw new IOException("status is " + statusCode);
    }

    /**
     * GET方式请求
     *
     * @param uri
     *            服务器的uri要用物理IP或域名,不识别localhost或127.0.0.1形式!
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String get(String uri, Map<String, String> paramMap)
            throws ClientProtocolException, IOException {

        StringBuilder sb = new StringBuilder(uri);
        if (paramMap != null) {
            boolean isBegin = true;
            for (String key : paramMap.keySet()) {
                if (isBegin) {
                    sb.append("?").append(key).append("=")
                            .append(paramMap.get(key));
                    isBegin = false;
                } else {
                    sb.append("&").append(key).append("=")
                            .append(paramMap.get(key));
                }

            }
        }
        HttpGet httpGet = new HttpGet(sb.toString());
        CloseableHttpClient httpClient = HttpClients.createDefault();
//        HttpClient httpClient = new DefaultHttpClient();
        HttpResponse httpResponse = httpClient.execute(httpGet);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
//			String result = EntityUtils.toString(httpResponse.getEntity());
            return EntityUtils.toString(httpResponse.getEntity());
        }
        throw new IOException("status is " + statusCode);
    }

    /**
     * GET方式请求https
     *
     * @param uri
     *            服务器的uri要用物理IP或域名,不识别localhost或127.0.0.1形式!
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String httpsGet(String uri, String keyFile, String keyPwd)
            throws Exception {
        HttpGet httpGet = new HttpGet(uri);
        HttpClient httpClient = newHttpsClient(keyFile, keyPwd);
        HttpResponse httpResponse = httpClient.execute(httpGet);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
//			String result = EntityUtils.toString(httpResponse.getEntity(),
//					DEFAULT_ENCODING);
            return  EntityUtils.toString(httpResponse.getEntity(),
                    DEFAULT_ENCODING);
        }
        throw new IOException("status is " + statusCode);
    }

    /**
     * POST方式请求
     *
     * @param uri
     *            服务器的uri要用物理IP或域名,不识别localhost或127.0.0.1形式!
     * @param paramMap
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String post(String uri, Map<String, Object> paramMap)
            throws ClientProtocolException, IOException {
        HttpPost httpPost = new HttpPost(uri);
        JSONObject param2= new JSONObject();
        if (paramMap != null) {
            for (String key : paramMap.keySet()) {
                param2.put(key, paramMap.get(key));
            }
            StringEntity stringEntity = new StringEntity(param2.toString());
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
            return EntityUtils.toString(httpResponse.getEntity(),
                    DEFAULT_ENCODING);
        }
        throw new IOException("status is " + statusCode);
    }

    public static String postForm(String uri, Map<String, String> paramMap) throws IOException {
        return postEncoding(uri, paramMap);
    }

    /**
     * POST方式请求，UTF-8编码发送内容
     *
     * @param uri
     * @param paramMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String postEncoding(String uri, Map<String, String> paramMap)
            throws ClientProtocolException, IOException {
        HttpPost httpPost = new HttpPost(uri);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        if (paramMap != null) {
            for (String key : paramMap.keySet()) {
                params.add(new BasicNameValuePair(key, paramMap.get(key)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(params,
                    DEFAULT_ENCODING));
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
            return EntityUtils.toString(httpResponse.getEntity(),
                    DEFAULT_ENCODING);
        }
        throw new IOException("status is " + statusCode);
    }

    /**
     * POST方式请求
     *
     * @param uri
     *            服务器的uri要用物理IP或域名,不识别localhost或127.0.0.1形式!
     * @param paramMap
     * @param headers
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String post(String uri, Map<String, String> paramMap,
                              Map<String, String> headers) throws ClientProtocolException,
            IOException {
        HttpPost httpPost = new HttpPost(uri);
        if (headers != null) {
            for (String key : headers.keySet()) {
                httpPost.setHeader(key, headers.get(key));
            }
        }
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        if (paramMap != null) {
            for (String key : paramMap.keySet()) {
                params.add(new BasicNameValuePair(key, paramMap.get(key)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(params,
                    DEFAULT_ENCODING));
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
            return EntityUtils.toString(httpResponse.getEntity(),
                    DEFAULT_ENCODING);
        }
        throw new IOException("status is " + statusCode);
    }

    /**
     * POST方式请求https
     *
     * @param uri
     *            服务器的uri要用物理IP或域名,不识别localhost或127.0.0.1形式!
     * @param paramMap
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String httpsPost(String uri, Map<String, String> paramMap,
                                   String keyFile, String keyPwd) throws ClientProtocolException,
            IOException, Exception {
        HttpPost httpPost = new HttpPost(uri);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        if (paramMap != null) {
            for (String key : paramMap.keySet()) {
                params.add(new BasicNameValuePair(key, paramMap.get(key)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(params,
                    DEFAULT_ENCODING));
        }
        HttpResponse httpResponse = newHttpsClient(keyFile, keyPwd).execute(
                httpPost);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
            return EntityUtils.toString(httpResponse.getEntity());
        }
        throw new IOException("status is " + statusCode);
    }

    /*
     * 新建httpsClient
     */
    private static HttpClient newHttpsClient(String keyFile, String keyPwd)
            throws Exception {
        KeyStore trustStore = KeyStore.getInstance("BKS");
        trustStore.load(new FileInputStream(new File(keyFile)),
                keyPwd.toCharArray());
        SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
        Scheme sch = new Scheme("https", socketFactory, 8443);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        httpClient.getConnectionManager().getSchemeRegistry().register(sch);
        return httpClient;
    }

    /**
     * post请求发送传输obj对象
     *
     * @param uri
     * @param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String postOfObject(String uri, Object obj)
            throws ClientProtocolException, IOException {
        String params = JSON.toJSONString(obj);
        return HttpClientUtil.postJson(uri, params);

    }

    /**
     * 针对http传输json数据处理
     *
     * @param uri
     * @param parameters
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String postJson(String uri, String parameters)
            throws ClientProtocolException, IOException {
        HttpPost httpPost = new HttpPost(uri);
        if (parameters != null) {
            StringEntity entity = new StringEntity(parameters);
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
            return EntityUtils.toString(httpResponse.getEntity(),
                    DEFAULT_ENCODING);
        }
        throw new IOException("status is " + statusCode);
    }

    /**
     * 针对http传输json数据处理
     *
     * @param uri
     * @param parameters
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String postByJson(String uri, String parameters)
            throws ClientProtocolException, IOException {
        HttpPost httpPost = new HttpPost(uri);
        if (parameters != null) {
            StringEntity entity = new StringEntity(parameters,"UTF-8");
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int statusCode;
        if ((statusCode = httpResponse.getStatusLine().getStatusCode()) == 200) {
            return EntityUtils.toString(httpResponse.getEntity(),
                    DEFAULT_ENCODING);
        }
        throw new IOException("status is " + statusCode);
    }
}
